gdk/surface: Delay gdk_surface_request_motion() requests internally
authorCarlos Garnacho <carlosg@gnome.org>
Tue, 8 Dec 2020 20:33:06 +0000 (21:33 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Tue, 8 Dec 2020 22:27:03 +0000 (23:27 +0100)
Those requests are received while dealing with the ::layout frame
clock phase, this has the unintended side effect of making the
frame clock "rewind" to handle ::flush-events again during this
frame, which delays everything and practically halves the frame
rate.

We do intend to make the motion events dispatches on the next frame,
so do this in an idle at a slightly lower priority than layout/draw,
so the ::flush-events phase is actually requested for the next frame.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3264
gdk/gdksurface.c
gdk/gdksurfaceprivate.h

index 012864479a65bf7895ee56f9ff9a3cb4f18fcf24..b6f739c5c071f2a7a2c01b86b59132e6048b95ca 100644 (file)
@@ -681,6 +681,8 @@ gdk_surface_finalize (GObject *object)
 {
   GdkSurface *surface = GDK_SURFACE (object);
 
+  g_clear_handle_id (&surface->request_motion_id, g_source_remove);
+
   g_signal_handlers_disconnect_by_func (surface->display,
                                         seat_removed_cb, surface);
 
@@ -2408,6 +2410,19 @@ gdk_surface_flush_events (GdkFrameClock *clock,
   surface->frame_clock_events_paused = TRUE;
 }
 
+static gboolean
+request_motion_cb (void *data)
+{
+  GdkSurface *surface = GDK_SURFACE (data);
+  GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
+
+  if (clock)
+    gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
+  surface->request_motion_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 gdk_surface_resume_events (GdkFrameClock *clock,
                            void          *data)
@@ -2419,6 +2434,13 @@ gdk_surface_resume_events (GdkFrameClock *clock,
       _gdk_display_unpause_events (surface->display);
       surface->frame_clock_events_paused = FALSE;
     }
+
+  if (surface->request_motion)
+    {
+      surface->request_motion_id =
+        g_idle_add_full (GDK_PRIORITY_REDRAW + 1,
+                         request_motion_cb, surface, NULL);
+    }
 }
 
 static void
@@ -2912,13 +2934,7 @@ gdk_surface_handle_event (GdkEvent *event)
 void
 gdk_surface_request_motion (GdkSurface *surface)
 {
-  GdkFrameClock *frame_clock;
-
   surface->request_motion = TRUE;
-
-  frame_clock = gdk_surface_get_frame_clock (surface);
-  if (frame_clock)
-    gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
 }
 
 /**
index 27a3966fe75ea99548b720eac57dfe663ebec4c5..2126371853cc0dcff763d2fb2ae2f50b968e89e1 100644 (file)
@@ -80,6 +80,8 @@ struct _GdkSurface
   guint shortcuts_inhibited : 1;
   guint request_motion : 1;
 
+  guint request_motion_id;
+
   struct {
     GdkGravity surface_anchor;
     GdkGravity rect_anchor;